module WsClient

	class WorkerThreadPool
		def initialize(workers)
			@mutex = Mutex.new
			@cond = ConditionVariable.new
			@queue = []
			@workers = workers.times.map { create_worker }
			@close = :false
		end
		
		def add(*args, &block)
			raise ArgumentError.new("No block given") unless block_given?
			@mutex.synchronize do
				break if @close != :false
				@queue << [args, block]
				@cond.signal
			end
		end
		
		def close(wait = false)
			stop_worker(wait ? :wait : :close)
		end
		
		private
		
		def create_worker
			Thread.new do
				exit = proc do
					if @close == :close || (@close == :wait and @queue.empty?)
						Thread.exit
					end
				end
			
				while true do
					args, block = nil
					
					@mutex.synchronize do
						exit.call
					
						while @queue.empty? do
							@cond.wait(@mutex)
							exit.call
						end
						
						args, block = @queue.pop
					end
					
					block.call(*args)
				end
			end
		end
		
		def stop_worker(how)
			@mutex.synchronize do
				@close = how
				@cond.broadcast
			end
		end
	end

end
